﻿#pragma once
#include<winsock.h>
#pragma comment(lib,"ws2_32.lib")

#include<iostream>


#include "sha1.h"
#include "base64.h"
#include "MyTools.h"
#include "HandleWS.h"


/// <summary>
/// 子线程：单独处理一个socket通信
/// </summary>
/// <param name="clientSocket"></param>
extern void CorePrint(char* msg);
void SubThread(SOCKET clientSocket)
{
	//
	// 接收握手请求
	//	
	char shackeHand_recvBuffer[2000];
	memset(shackeHand_recvBuffer, 0, sizeof(shackeHand_recvBuffer));
	int recvLen = recv(clientSocket, shackeHand_recvBuffer, 2000, 0);
	if (recvLen < 0) { printf("接受数据失败！\n"); return; }
	printf("【WebSocket握手】接收客户端数据（len=%d）\n%s\n", recvLen, shackeHand_recvBuffer);

	///
	/// 解析握手请求数据
	/// 

	// 查找协议中的Sec-WebSocket-Key 字段
	std::string revDataString = shackeHand_recvBuffer;
	int keyIndex = revDataString.find("Sec-WebSocket-Key");

	// 截取 Sec-WebSocket-Key 字段的内容
	std::string secWebSocketKeyString = revDataString.substr(keyIndex + 19, 24);

	// 加密拼接 WebSocket-Key
	char encodedKey[1024] = "";
	PackShakeHandleKey(secWebSocketKeyString, OUT encodedKey);
	printf("【WebSocket握手】加密客户端发来的WebSocket-Key，封装http报文：\n%s\n", encodedKey);

	///
	/// 握手响应，完成WebSocket连接
	///
	int shackeHand_sendLen = send(clientSocket, encodedKey, strlen(encodedKey), 0);
	if (shackeHand_sendLen < 0) { printf("响应WS握手失败！\n"); return; }
	printf("【WebSocket握手】握手对接成功！开始基于WebSocket协议通信...\n");

	/// 
	/// 开始基于WebSocket协议的数据通信
	/// 
	while (true) {

		//
		// 从客户端读数据
		//

		// 读WS消息头
		WSHeader wsHeader;
		if (AnalyzeWSHeader(clientSocket, OUT wsHeader) == false) { return; }
		printf("【WebSocket协议通信】接收到WS消息头：PayloadSize=%d(d)，是否掩码加密=%d \n", wsHeader.PayloadSize, wsHeader.isMASK);

		// 读WS数据负载
		char* payLoadData = (char*)malloc(wsHeader.PayloadSize); memset(payLoadData, 0, wsHeader.PayloadSize);
		if (recv(clientSocket, payLoadData, wsHeader.PayloadSize, 0) <= 0) { std::cout << "【WebSocket协议通信】读取Socket数据失败，连接已断开...\n" << std::endl; return; }

		printf("【WebSocket协议通信】接收到WS数据负载（原始）：\n");
		for (UINT64 i = 0; i < wsHeader.PayloadSize; i++)
			printf("%02x ", (BYTE)payLoadData[i]);
		printf("\n");

		// 解码WS数据负载
		char* decodePayLoadData = (char*)malloc(wsHeader.PayloadSize + 1); memset(decodePayLoadData, 0, wsHeader.PayloadSize + 1); //额外多申请1字节作为多字节文本的终止符
		if (wsHeader.isMASK)
		{
			if (false == DecodePayload(wsHeader.maskArray, payLoadData, wsHeader.PayloadSize, OUT decodePayLoadData, wsHeader.PayloadSize)) { printf("【WebSocket协议通信】读取Socket数据失败，连接已断开...\n\n"); closesocket(clientSocket); return; }
			printf("【WebSocket协议通信】WS数据负载（解码后）：\n");
			for (int i = 0; i < wsHeader.PayloadSize; i++) {
				printf("%02x ", (BYTE)decodePayLoadData[i]);
			}
			printf("\n");
		}
		else { memcpy(decodePayLoadData, payLoadData, wsHeader.PayloadSize); }

		// 将浏览器发来的 Unicode(UTF-8)多字节字符串 转换为 GB2312(ANSI)多字节字符串
		char* multiByteANSI = MyTools::multiByteUTF8_to_multiByteANSI(decodePayLoadData);
		printf("【WebSocket协议通信】转换WS数据负载（UTF-8字符串 转为 ANSI字符串）：%s\n", multiByteANSI);




		// 进入打印流程
		CorePrint(multiByteANSI);

		//
		free(multiByteANSI);
		free(payLoadData);
		free(decodePayLoadData);

		//
		// 向客户端发送数据
		//

		//char msg[] = "hello 你好呀，谷歌！";

		//// 将GB2312(ANSI)多字节字符串 转为 浏览器能识别的Unicode(UTF-8)多字节字符串
		//char* multiByte_UTF8 =  MyTools::multiByteANSI_to_multiByteUTF8(msg);

		//// 将消息封装为WS格式
		//char msg_WS[1200];
		//UINT64 sendWSLen = EncodeWS(multiByte_UTF8, msg_WS, sizeof(msg_WS));
		//if (sendWSLen != -1)
		//{
		//	// 发送WS格式消息
		//	send(clientSocket, msg_WS, sendWSLen, 0);
		//}

		//// release
		//free(multiByte_UTF8);
	}
}

void WS_startup()
{

	// 初始化套接字库
	WORD w_req = MAKEWORD(2, 2);//版本号
	WSADATA wsadata;
	int err = WSAStartup(w_req, &wsadata);
	if (err != 0) { printf("初始化套接字库失败！"); return; }
	printf("初始化套接字库成功！\n");

	// 检测版本号
	if (LOBYTE(wsadata.wVersion) != 2 || HIBYTE(wsadata.wHighVersion) != 2) { printf("套接字库版本号不符！"); WSACleanup(); return; }
	printf("验证套接字库版本正确！\n");

	// 创建服务端监听Socket
	SOCKADDR_IN server_addr;
	server_addr.sin_family = AF_INET;
	server_addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
	server_addr.sin_port = htons(9999); //监听9999端口
	SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, 0);
	if (bind(serverSocket, (SOCKADDR*)&server_addr, sizeof(SOCKADDR)) == SOCKET_ERROR) { printf("套接字绑定失败！"); WSACleanup(); return; }

	while (true)
	{
		// 开始服务端监听
		if (listen(serverSocket, SOMAXCONN) < 0) { printf("设置监听状态失败！"); WSACleanup(); return; }
		printf("服务端正在监听....\n");

		// 接受连接请求
		SOCKADDR_IN accept_addr;
		int len = sizeof(SOCKADDR);
		SOCKET clientSocket = accept(serverSocket, (SOCKADDR*)&accept_addr, &len);
		if (clientSocket == SOCKET_ERROR) { printf("接受连接请求发生错误！"); WSACleanup(); return; }

		// 在子线程中处理本次通信
		printf("--------------------------成功建立Socket连接---------------------------\n");
		HANDLE hThread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)SubThread, (LPVOID)clientSocket, 0, 0);

	}

	//释放资源
	closesocket(serverSocket);
	WSACleanup();
	system("pause");
}